package org.budo.graph.service.util;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.budo.sentinel.util.SentinelUtil;
import org.budo.support.lang.util.NumberUtil;
import org.budo.support.lang.util.ReflectUtil;
import org.budo.support.lang.util.StringUtil;
import org.springframework.context.ApplicationContext;

import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
import com.alibaba.druid.stat.DruidStatService;

import lombok.extern.slf4j.Slf4j;

/**
 * @author lmw
 */
@Slf4j
public class GraphSentinelUtil {
    private static final boolean HAS_SENTINEL = ReflectUtil.hasClass("com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager");

    public static String update(ApplicationContext applicationContext, String url) {
        Map<String, String> parameters = DruidStatService.getParameters(url);
        String resource = StringUtil.trim(parameters.get("resource"));
        String qpsMax = StringUtil.trim(parameters.get("qpsMax"));

        Double count = NumberUtil.toDouble(qpsMax);

        boolean found = false;
        List<FlowRule> rules_b = new ArrayList<FlowRule>();
        List<FlowRule> rules_a = FlowRuleManager.getRules();
        for (FlowRule rule : rules_a) {
            if (null == rule) {
                continue;
            }

            String res = rule.getResource();
            if (resource.equals(res)) { // 修改
                log.info("#37 update role, resource = " + resource + ", count = " + rule.getCount() + " > " + count);

                rules_b.add(SentinelUtil.threadFlowRule(resource, count));
                found = true;
            } else {
                rules_b.add(rule);
            }
        }

        // 新增
        if (!found) {
            log.info("#48 new role, resource = " + resource + ", count = " + count);

            rules_b.add(SentinelUtil.threadFlowRule(resource, count));
        }

        // 重新加载
        FlowRuleManager.loadRules(rules_b);
        return "done";
    }

    public static Object flowRuleCount(String uri) {
        if (!HAS_SENTINEL) {
            return -1;
        }

        Double count = SentinelUtil.flowRuleCount(uri);
        return null == count ? -2 : count;
    }
}